/*
#####################################################################
####################	   T R I B U I T 		#####################
#####################################################################

Copyright (C) 2010  Christoph Schnack, Berlin (Germany)

This file is part of Tribuit.

    Tribuit is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Tribuit is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Tribuit.  If not, see <http://www.gnu.org/licenses/>.


########################################################################
*/
package JukeBox;


import javax.sound.midi.*;
import Settings.*;

public class JukeBox implements MetaEventListener{
	Sequencer sequencer;
    Sequence correctSeq,wrongSeq, totallyFailedSeq,veryBadSeq,badSeq,pleasableSeq,improvableSeq,goodSeq,veryWellSeq;
    Settings SET;
    
    public JukeBox(Settings set){
    	SET=set;
    	int volume = SET.getVolume()<=30?31:SET.getVolume();
    	try{
    		veryWellSeq = new Sequence(Sequence.PPQ,4);
    		goodSeq = new Sequence(Sequence.PPQ,4);
    		pleasableSeq = new Sequence(Sequence.PPQ,4);
    		improvableSeq = new Sequence(Sequence.PPQ,4);
    		totallyFailedSeq = new Sequence(Sequence.PPQ,4);
    		badSeq = new Sequence(Sequence.PPQ,4);
    		veryBadSeq = new Sequence(Sequence.PPQ,4);
    		wrongSeq = new Sequence(Sequence.PPQ,4);
    		correctSeq = new Sequence(Sequence.PPQ,4);
    		
	    	sequencer = MidiSystem.getSequencer();
	    	
	    	int instClass = 1;
			int tone = 46;
	    	Track correctTrack = correctSeq.createTrack();
			correctTrack.add(midiEvent(192,instClass,12,0,1));
			correctTrack.add(midiEvent(144,instClass,tone,volume-20,1));
			correctTrack.add(midiEvent(128,instClass,tone,volume-20,2));
			correctTrack.add(midiEvent(144,instClass,tone+7,volume,2));
			correctTrack.add(midiEvent(128,instClass,tone+7,volume,6));
			
			tone = 50;
			Track wrongTrack = wrongSeq.createTrack();
			wrongTrack.add(midiEvent(192,instClass,30,0,1));
			wrongTrack.add(midiEvent(144,instClass,tone,volume,1));
			wrongTrack.add(midiEvent(128,instClass,tone,volume,4));
			
			tone = 60;
			Track totallyFailedTrack = totallyFailedSeq.createTrack();
			totallyFailedTrack.add(midiEvent(144,instClass,tone,volume-10,1));
			totallyFailedTrack.add(midiEvent(128,instClass,tone,volume-10,2));
			totallyFailedTrack.add(midiEvent(144,instClass,tone+5,volume-10,1));
			totallyFailedTrack.add(midiEvent(128,instClass,tone+5,volume-10,2));
			
			totallyFailedTrack.add(midiEvent(144,instClass,tone,volume,3));
			totallyFailedTrack.add(midiEvent(128,instClass,tone,volume,4));
			totallyFailedTrack.add(midiEvent(144,instClass,tone+8,volume,3));
			totallyFailedTrack.add(midiEvent(128,instClass,tone+8,volume,4));
			
			totallyFailedTrack.add(midiEvent(144,instClass,tone,volume-10,8));
			totallyFailedTrack.add(midiEvent(128,instClass,tone,volume-10,26));
			totallyFailedTrack.add(midiEvent(144,instClass,tone-1,volume-10,8));
			totallyFailedTrack.add(midiEvent(128,instClass,tone-1,volume-10,11));
			totallyFailedTrack.add(midiEvent(144,instClass,tone-2,volume-10,11));
			totallyFailedTrack.add(midiEvent(128,instClass,tone-2,volume-10,14));
			totallyFailedTrack.add(midiEvent(144,instClass,tone-3,volume-10,14));
			totallyFailedTrack.add(midiEvent(128,instClass,tone-3,volume-10,17));
			totallyFailedTrack.add(midiEvent(144,instClass,tone-4,volume-10,17));
			totallyFailedTrack.add(midiEvent(128,instClass,tone-4,volume-10,26));
			
			Track veryBadTrack = veryBadSeq.createTrack();
			veryBadTrack.add(midiEvent(192,instClass,1,0,1));
			veryBadTrack.add(midiEvent(144,instClass,tone,volume-20,1));
			veryBadTrack.add(midiEvent(128,instClass,tone,volume-20,2));
			veryBadTrack.add(midiEvent(144,instClass,tone+13,volume-20,1));
			veryBadTrack.add(midiEvent(128,instClass,tone+13,volume-20,2));
			
			veryBadTrack.add(midiEvent(144,instClass,tone,volume-20,2));
			veryBadTrack.add(midiEvent(128,instClass,tone,volume-20,3));
			veryBadTrack.add(midiEvent(144,instClass,tone+13,volume-20,2));
			veryBadTrack.add(midiEvent(128,instClass,tone+13,volume-20,3));
			
			veryBadTrack.add(midiEvent(144,instClass,tone,volume-20,3));
			veryBadTrack.add(midiEvent(128,instClass,tone,volume-20,4));
			veryBadTrack.add(midiEvent(144,instClass,tone+13,volume-20,3));
			veryBadTrack.add(midiEvent(128,instClass,tone+13,volume-20,4));
			
			veryBadTrack.add(midiEvent(144,instClass,tone-2,volume,4));
			veryBadTrack.add(midiEvent(128,instClass,tone-2,volume,12));
			veryBadTrack.add(midiEvent(144,instClass,tone+11,volume,4));
			veryBadTrack.add(midiEvent(128,instClass,tone+11,volume,12));
			
			Track badTrack = badSeq.createTrack();
			badTrack.add(midiEvent(192,instClass,1,0,1));
			badTrack.add(midiEvent(144,instClass,tone,volume,1));
			badTrack.add(midiEvent(128,instClass,tone,volume,2));
			badTrack.add(midiEvent(144,instClass,tone+4,volume,2));
			badTrack.add(midiEvent(128,instClass,tone+4,volume,3));
			badTrack.add(midiEvent(144,instClass,tone+7,volume,3));
			badTrack.add(midiEvent(128,instClass,tone+7,volume,4));
			
			badTrack.add(midiEvent(144,instClass,tone,volume,6));
			badTrack.add(midiEvent(128,instClass,tone,volume,12));
			badTrack.add(midiEvent(144,instClass,tone+5,volume,6));
			badTrack.add(midiEvent(128,instClass,tone+5,volume,12));
			badTrack.add(midiEvent(144,instClass,tone+6,volume,6));
			badTrack.add(midiEvent(128,instClass,tone+6,volume,12));
			
			Track pleasableTrack = pleasableSeq.createTrack();
			pleasableTrack.add(midiEvent(192,instClass,1,0,1));
			pleasableTrack.add(midiEvent(144,instClass,tone,volume-30,1));
			pleasableTrack.add(midiEvent(128,instClass,tone,volume-30,2));
			pleasableTrack.add(midiEvent(144,instClass,tone+2,volume-10,2));
			pleasableTrack.add(midiEvent(128,instClass,tone+2,volume-10,3));
			pleasableTrack.add(midiEvent(144,instClass,tone+7,volume,3));
			pleasableTrack.add(midiEvent(128,instClass,tone+7,volume,4));
			
			pleasableTrack.add(midiEvent(144,instClass,tone,volume,6));
			pleasableTrack.add(midiEvent(144,instClass,tone+2,volume,6));
			pleasableTrack.add(midiEvent(144,instClass,tone+7,volume,6));
			pleasableTrack.add(midiEvent(128,instClass,tone,volume,12));
			pleasableTrack.add(midiEvent(128,instClass,tone+2,volume,12));
			pleasableTrack.add(midiEvent(128,instClass,tone+7,volume,12));
			
			Track improvableTrack = improvableSeq.createTrack();
			improvableTrack.add(midiEvent(192,instClass,1,0,1));
			improvableTrack.add(midiEvent(144,instClass,tone,volume-30,1));
			improvableTrack.add(midiEvent(128,instClass,tone,volume-30,2));
			improvableTrack.add(midiEvent(144,instClass,tone+3,volume-10,2));
			improvableTrack.add(midiEvent(128,instClass,tone+3,volume-10,3));
			improvableTrack.add(midiEvent(144,instClass,tone+7,volume,3));
			improvableTrack.add(midiEvent(128,instClass,tone+7,volume,4));
			
			improvableTrack.add(midiEvent(144,instClass,tone,volume,6));
			improvableTrack.add(midiEvent(144,instClass,tone+3,volume,6));
			improvableTrack.add(midiEvent(144,instClass,tone+7,volume,6));
			improvableTrack.add(midiEvent(128,instClass,tone,volume,12));
			improvableTrack.add(midiEvent(128,instClass,tone+3,volume,12));
			improvableTrack.add(midiEvent(128,instClass,tone+7,volume,12));
			
			Track goodTrack = goodSeq.createTrack();
			goodTrack.add(midiEvent(192,instClass,1,0,1));
			goodTrack.add(midiEvent(144,instClass,tone,volume-30,1));
			goodTrack.add(midiEvent(128,instClass,tone,volume-30,2));
			goodTrack.add(midiEvent(144,instClass,tone+4,volume-10,2));
			goodTrack.add(midiEvent(128,instClass,tone+4,volume-10,3));
			goodTrack.add(midiEvent(144,instClass,tone+7,volume,3));
			goodTrack.add(midiEvent(128,instClass,tone+7,volume,4));
			
			goodTrack.add(midiEvent(144,instClass,tone,volume,6));
			goodTrack.add(midiEvent(144,instClass,tone+4,volume,6));
			goodTrack.add(midiEvent(144,instClass,tone+7,volume,6));
			goodTrack.add(midiEvent(128,instClass,tone,volume,12));
			goodTrack.add(midiEvent(128,instClass,tone+4,volume,12));
			goodTrack.add(midiEvent(128,instClass,tone+7,volume,12));
			
			tone = 40;
			Track veryWellTrack= veryWellSeq.createTrack();
			veryWellTrack.add(midiEvent(192,instClass,112,0,1));
			veryWellTrack.add(midiEvent(144,instClass,tone,volume,1));
			veryWellTrack.add(midiEvent(128,instClass,tone,volume,2));
			veryWellTrack.add(midiEvent(144,instClass,tone-2,volume-30,2));
			veryWellTrack.add(midiEvent(128,instClass,tone-2,volume-30,3));
			veryWellTrack.add(midiEvent(144,instClass,tone-2,volume-30,3));
			veryWellTrack.add(midiEvent(128,instClass,tone-2,volume-30,4));
			veryWellTrack.add(midiEvent(144,instClass,tone,volume,4));
			veryWellTrack.add(midiEvent(128,instClass,tone,volume,5));
			veryWellTrack.add(midiEvent(144,instClass,tone-2,volume-30,5));
			veryWellTrack.add(midiEvent(128,instClass,tone-2,volume-30,6));
			veryWellTrack.add(midiEvent(144,instClass,tone-2,volume-30,6));
			veryWellTrack.add(midiEvent(128,instClass,tone-2,volume-30,7));
			
			veryWellTrack.add(midiEvent(144,instClass,tone,volume,7));
			veryWellTrack.add(midiEvent(144,instClass,tone+7,volume,7));
			veryWellTrack.add(midiEvent(128,instClass,tone,volume,10));
			veryWellTrack.add(midiEvent(128,instClass,tone+7,volume,10));
			
			veryWellTrack.add(midiEvent(144,instClass,tone+3,volume,10));
			veryWellTrack.add(midiEvent(144,instClass,tone+10,volume,10));
			veryWellTrack.add(midiEvent(128,instClass,tone+3,volume,13));
			veryWellTrack.add(midiEvent(128,instClass,tone+10,volume,13));
			
			veryWellTrack.add(midiEvent(144,instClass,tone+5,volume,13));
			veryWellTrack.add(midiEvent(144,instClass,tone+12,volume,13));
			veryWellTrack.add(midiEvent(128,instClass,tone+5,volume,19));
			veryWellTrack.add(midiEvent(128,instClass,tone+12,volume,19));
    	}
    	catch(Exception e){
    		e.printStackTrace();
    	}
    	sequencer.addMetaEventListener(this);
    }
    
    public void meta( MetaMessage event ) {
    	if ( event.getType() == 47 ) { // end of stream
    		sequencer.stop();
    		sequencer.close();
    	}
    }

    
	public void play(Sequence seq){
		if(!SET.isSoundOn() || SET.getVolume()==0 || seq==null || sequencer == null) return;
		try{
			sequencer.open();
			sequencer.setSequence(seq);
			sequencer.start();
			while(sequencer.isRunning()){
				Thread.sleep(500);
			}
		}
		catch(Exception e){e.printStackTrace();}
	}

	public MidiEvent midiEvent(int comd,int chan, int one, int two, int tick){
		MidiEvent event = null;
		try{
			ShortMessage a = new ShortMessage();
			a.setMessage(comd, chan,one, two);
			event=new MidiEvent(a,tick);
		}
		catch(Exception e){e.printStackTrace();}
		return event;
	}
	
	public void playCorrect(){
		sequencer.setTempoInBPM(80);
		play(correctSeq);
	}
	
	public void playWrong(){
		sequencer.setTempoInBPM(80);
		play(wrongSeq);
	}
	
	public void playTotallyFailed(){
		sequencer.setTempoInBPM(100);
		play(totallyFailedSeq);
	}
	
	public void playVerybad(){
		sequencer.setTempoInBPM(60);
		play(veryBadSeq);
	}
	
	public void playBad(){
		sequencer.setTempoInBPM(100);
		play(badSeq);
	}
	
	public void playPleasable(){
		sequencer.setTempoInBPM(100);
		play(pleasableSeq);
	}
	
	public void playImprovable(){
		sequencer.setTempoInBPM(100);
		play(improvableSeq);
	}
	
	public void playGood(){
		sequencer.setTempoInBPM(100);
		play(goodSeq);
	}
	
	public void playVeryWell(){
		sequencer.setTempoInBPM(90);
		play(veryWellSeq);
	}
}
